/*
Copyright (c) 2008
Heka Lok <heka.lok@gmail.com>
David Feilen <bastian.mezurashii@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

module defl.c.ecore.ecore;

version (GNU)
{
  version (Unix) 
  {
    version = GNUUnix;
    public import std.c.unix.unix;
  }
}

extern (C)
{
  const int ECORE_CALLBACK_CANCEL = 0;
  const int ECORE_CALLBACK_RENEW  = 1;

  const int ECORE_EVENT_NONE            = 0;
  const int ECORE_EVENT_SIGNAL_USER     = 1; /**< User signal event */
  const int ECORE_EVENT_SIGNAL_HUP      = 2; /**< Hup signal event */
  const int ECORE_EVENT_SIGNAL_EXIT     = 3; /**< Exit signal event */
  const int ECORE_EVENT_SIGNAL_POWER    = 4; /**< Power signal event */
  const int ECORE_EVENT_SIGNAL_REALTIME = 5; /**< Realtime signal event */
  const int ECORE_EVENT_COUNT           = 6;

  extern int ECORE_EXE_EVENT_ADD;
  extern int ECORE_EXE_EVENT_DEL;
  extern int ECORE_EXE_EVENT_DATA;
  extern int ECORE_EXE_EVENT_ERROR;

  enum Ecore_Fd_Handler_Flags
  {
    ECORE_FD_READ  = 1,  /**< Fd Read mask */
    ECORE_FD_WRITE = 2, /**< Fd Write mask */
    ECORE_FD_ERROR = 4 /**< Fd Error mask */
  };

  enum Ecore_Exe_Flags /* flags for executing a child with its stdin and/or stdout piped back */
  {
    ECORE_EXE_PIPE_READ = 1, /**< Exe Pipe Read mask */
    ECORE_EXE_PIPE_WRITE = 2, /**< Exe Pipe Write mask */
    ECORE_EXE_PIPE_ERROR = 4, /**< Exe Pipe error mask */
    ECORE_EXE_PIPE_READ_LINE_BUFFERED = 8, /**< Reads are buffered until a newline and delivered 1 event per line */
    ECORE_EXE_PIPE_ERROR_LINE_BUFFERED = 16, /**< Errors are buffered until a newline and delivered 1 event per line */
    ECORE_EXE_PIPE_AUTO = 32, /**< stdout and stderr are buffered automatically */
    ECORE_EXE_RESPAWN = 64, /**< FIXME: Exe is restarted if it dies */
    ECORE_EXE_USE_SH = 128 /**< Use /bin/sh to run the command. */
  };

  enum Ecore_Poller_Type /* Poller types */
  {
    ECORE_POLLER_CORE = 0 /**< The core poller interval */
  };

  version (GNUUnix)
  {
    alias void Ecore_Exe; /**< A handle for spawned processes */
  }
  alias void Ecore_Timer; /**< A handle for timers */
  alias void Ecore_Idler; /**< A handle for idlers */
  alias void Ecore_Idle_Enterer; /**< A handle for idle enterers */
  alias void Ecore_Idle_Exiter; /**< A handle for idle exiters */
  alias void Ecore_Fd_Handler; /**< A handle for Fd hanlders */
  alias void Ecore_Event_Handler; /**< A handle for an event handler */
  alias void Ecore_Event_Filter; /**< A handle for an event filter */
  alias void Ecore_Event; /**< A handle for an event */
  alias void Ecore_Animator; /**< A handle for animators */
  alias void Ecore_Poller; /**< A handle for pollers */

  struct Ecore_Event_Signal_User /** User signal event */
  {
    int   number; /**< The signal number. Either 1 or 2 */
    void *ext_data; /**< Extension data - not used */

    version (GNUUnix)
    {
      siginfo_t data; /**< Signal info */
    }
  };

  struct Ecore_Event_Signal_Hup /** Hup signal event */
  {
    void *ext_data; /**< Extension data - not used */

    version (GNUUnix)
    {
      siginfo_t data; /**< Signal info */
    }
  };

  struct Ecore_Event_Signal_Exit /** Exit request event */
  {
    bool   interrupt; /**< Set if the exit request was an interrupt  signal*/
    bool   quit;      /**< set if the exit request was a quit signal */
    bool   terminate; /**< Set if the exit request was a terminate singal */
    void  *ext_data;  /**< Extension data - not used */

    version (GNUUnix)
    {
      siginfo_t data; /**< Signal info */
    }
  };

  struct Ecore_Event_Signal_Power /** Power event */
  {
    void *ext_data;     /**< Extension data - not used */

    version (GNUUnix)
    {
      siginfo_t data; /**< Signal info */
    }
  };

  struct Ecore_Event_Signal_Realtime /** Realtime event */
  {
    int num; /**< The realtime signal's number */

    version (GNUUnix)
    {
      siginfo_t data; /**< Signal info */
    }
  };

  version (GNUUnix)
  {
    struct Ecore_Exe_Event_Add /** Process add event */
    {
      Ecore_Exe *exe;      /**< The handle to the added process */
      void      *ext_data; /**< Extension data - not used */
    };

    struct Ecore_Exe_Event_Del /** Process exit event */
    {
      pid_t         pid;         /**< The process ID of the process that exited */
      int           exit_code;   /**< The exit code of the process */
      Ecore_Exe    *exe;         /**< The handle to the exited process, or NULL if not found */
      int           exit_signal; /**< The signal that caused the process to exit */
      bool          exited;      /**< set to 1 if the process exited of its own accord */
      bool          signalled;   /**< set to 1 id the process exited due to uncaught signal */
      void         *ext_data;    /**< Extension data - not used */
      siginfo_t     data;        /**< Signal info */
    };

    struct Ecore_Exe_Event_Data_Line /**< Lines from a child process */
    {
      char *line;
      int   size;
    };

    struct Ecore_Exe_Event_Data /** Data from a child process event */
    {
      Ecore_Exe *exe;  /**< The handle to the process */
      void      *data; /**< the raw binary data from the child process that was recieved */
      int        size; /**< the size of this data in bytes */
      Ecore_Exe_Event_Data_Line *lines; /**< an array of line data if line buffered, the last one has it's line member set to NULL */
    };
  }

  int  ecore_init();
  int  ecore_shutdown();

  void ecore_app_args_set(int argc, char **argv);
  void ecore_app_args_get(int *argc, char ***argv);
  void ecore_app_restart();

  /*XXX Not complete */
  Ecore_Event_Handler *ecore_event_handler_add(int type, int (*func) (void *data, int type, void *event), void *data);
  void                *ecore_event_handler_del(Ecore_Event_Handler *event_handler);
  Ecore_Event         *ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data);
  void                *ecore_event_del(Ecore_Event *event);
  int                  ecore_event_type_new();
  Ecore_Event_Filter  *ecore_event_filter_add(void * (*func_start) (void *data), int (*func_filter) (void *data, void *loop_data, int type, void *event), void (*func_end) (void *data, void *loop_data), void *data);
  void                *ecore_event_filter_del(Ecore_Event_Filter *ef);
  int                  ecore_event_current_type_get();
  void                *ecore_event_current_event_get();

  version (GNUUnix)
  {
    /* TODO */
    Ecore_Exe  *ecore_exe_run(char *exe_cmd, void *data);
    Ecore_Exe  *ecore_exe_pipe_run(char *exe_cmd, Ecore_Exe_Flags flags, void *data);
    int         ecore_exe_send(Ecore_Exe *exe, void *data, int size);
    void        ecore_exe_close_stdin(Ecore_Exe *exe);
    void        ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int start_lines, int end_lines);
    Ecore_Exe_Event_Data *ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags);
    void        ecore_exe_event_data_free(Ecore_Exe_Event_Data *data);
    void       *ecore_exe_free(Ecore_Exe *exe);
    pid_t       ecore_exe_pid_get(Ecore_Exe *exe);
    void        ecore_exe_tag_set(Ecore_Exe *exe, char *tag);
    char       *ecore_exe_tag_get(Ecore_Exe *exe);
    char       *ecore_exe_cmd_get(Ecore_Exe *exe);
    void       *ecore_exe_data_get(Ecore_Exe *exe);
    void        ecore_exe_pause(Ecore_Exe *exe);
    void        ecore_exe_continue(Ecore_Exe *exe);
    void        ecore_exe_terminate(Ecore_Exe *exe);
    void        ecore_exe_kill(Ecore_Exe *exe);
    void        ecore_exe_signal(Ecore_Exe *exe, int num);
    void        ecore_exe_hup(Ecore_Exe *exe);
  }

  /* TODO */
  Ecore_Idler *ecore_idler_add(int (*func) (void *data), void *data);
  void        *ecore_idler_del(Ecore_Idler *idler);

  /* TODO */
  Ecore_Idle_Enterer *ecore_idle_enterer_add(int (*func) (void *data), void *data);
  Ecore_Idle_Enterer *ecore_idle_enterer_before_add(int (*func) (void *data), void *data);
  void               *ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer);

  /* TODO */
  Ecore_Idle_Exiter *ecore_idle_exiter_add(int (*func) (void *data), void *data);
  void              *ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter);

  void              ecore_main_loop_iterate();
  void              ecore_main_loop_begin();
  void              ecore_main_loop_quit();

  /* TODO */
  Ecore_Fd_Handler *ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, int (*func) (void *data, Ecore_Fd_Handler *fd_handler), void *data, int (*buf_func) (void *buf_data, Ecore_Fd_Handler *fd_handler), void *buf_data);
  void              ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, void (*func) (void *data, Ecore_Fd_Handler *fd_handler), void *data);
  void             *ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler);
  int               ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler);
  int               ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags);
  void              ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags);

  double ecore_time_get();

  Ecore_Timer *ecore_timer_add(double interval, int (*func) (void *data), void *data);
  void        *ecore_timer_del(Ecore_Timer *timer);
  void         ecore_timer_interval_set(Ecore_Timer *timer, double interval);

  /* TODO */
  Ecore_Animator *ecore_animator_add(int (*func) (void *data), void *data);
  void           *ecore_animator_del(Ecore_Animator *animator);
  void            ecore_animator_frametime_set(double frametime);
  double          ecore_animator_frametime_get();

  /* TODO */
  void          ecore_poller_poll_interval_set(Ecore_Poller_Type type, double poll_time);
  double        ecore_poller_poll_interval_get(Ecore_Poller_Type type);
  Ecore_Poller *ecore_poller_add(Ecore_Poller_Type type, int interval, int (*func) (void *data), void *data);
  void         *ecore_poller_del(Ecore_Poller *poller);
}
